package com.youdo.helper;

import static com.youdo.uvccamera.CameraConstants.*;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbDevice;
import android.util.Log;
import android.view.SurfaceView;

import com.serenegiant.encoder.MediaMuxerWrapper;
import com.serenegiant.usb.DeviceFilter;
import com.serenegiant.usb.USBMonitor;
import com.serenegiant.uvccamera.R;
import com.serenegiant.widget.CameraViewInterface;
import com.youdo.service.BufferWrapper;
import com.youdo.service.CameraAction;
import com.youdo.service.UVCService;
import com.youdo.serviceclient.CameraClient;
import com.youdo.serviceclient.ICameraClient;
import com.youdo.serviceclient.ICameraClientCallback;
import com.youdo.uvccamera.CameraConstants;

import java.util.List;

/**
 * UVCCamera 帮助类
 * @author ljb
 * @date 2025.02.12
 * @email 568838953@qq.com
 * <p>
 * 支持分段录屏;支持debug模式;by ljb on 2025.03.03
 */
public class UVCCameraHelper {
    private static final String TAG = "UVCCameraHelper";
    @SuppressLint("StaticFieldLeak")
    private static UVCCameraHelper mCameraHelper;
    private boolean DEBUG = true;
    private USBMonitor mUSBMonitor;
    private ICameraClient mCameraClient;// 打开相机时创建
    private Context mContext;
    private CameraViewInterface mCameraView;
    private SurfaceView mCameraViewSub;
    private ConnectCallback listener;
    private boolean mEnableFrameCallback = false;// 回调的帧格式 UVCCamera.PIXEL_FORMAT_YUV
    private int mSaveMode = 0;
    private String mSavePath = DEFAULT_SAVE_PATH;
    private int mCurrentWidth = CameraConstants.DEFAULT_WIDTH;
    private int mCurrentHeight = CameraConstants.DEFAULT_HEIGHT;
    private int mSegmentPeriod;
    private boolean mAudioRecord;

    private UVCCameraHelper() {
    }

    /**
     * 获取单例
     */
    public static UVCCameraHelper getInstance() {
        if (mCameraHelper == null) {
            mCameraHelper = new UVCCameraHelper();
        }

        return mCameraHelper;
    }

    /**
     * 增加预览控件 SurfaceView
     * "formats":[{"index":1,"type":6,"default":1,
     * "size":["1920x1080","1280x1024","1280x960","1280x800","1280x720",
     * "1024x768","960x540","848x480","800x600","640x480","640x400","640x360",
     * "480x270","424x240","360x180","352x288","340x340","320x240","320x180",
     * "176x144","160x120","160x90"]}
     */
    public UVCCameraHelper setPreviewSize(final int width, final int height) {
        mCurrentWidth = width;
        mCurrentHeight = height;
        return this;
    }

    public UVCCameraHelper resize(final int width, final int height) {
        mCurrentWidth = width;
        mCurrentHeight = height;
        if (mCameraClient != null) {
            mCameraClient.resize(width, height);
        }
        return this;
    }

    /**
     * 设置分段时间
     */
    public UVCCameraHelper setSegmentPeriod(final int minute) {
        mSegmentPeriod = minute;
        return this;
    }

    /**
     * 设置分段时间
     */
    public UVCCameraHelper setAudioRecord(final boolean record) {
        mAudioRecord = record;
        return this;
    }


    /**
     * 增加预览控件 SurfaceView
     */
    public UVCCameraHelper addSurfaceView(SurfaceView cameraViewSub) {
        this.mCameraViewSub = cameraViewSub;
        return this;
    }

    /**
     * 是否打印数据
     */
    public UVCCameraHelper setDebugMode(boolean isDebug) {
        this.DEBUG = isDebug;
        return this;
    }

    /**
     * 增加预览控件,继承 CameraViewInterface 的 TextureView,支持显示和隐藏
     */
    public UVCCameraHelper addTextureView(CameraViewInterface cameraView) {
        this.mCameraView = cameraView;
        return this;
    }

    /**
     * 开启帧回调
     */
    public UVCCameraHelper enableFrameCallback(final boolean enable) {
        mEnableFrameCallback = enable;
        return this;
    }

    /**
     * 设置录像保存模式(0-内存低时删除掉最早一天的文件夹,1-覆盖模式/极端情况,只存2个,一个是上次录的，一个是当前在录的)
     */
    public UVCCameraHelper setSaveMode(final int mode) {
        mSaveMode = mode;
        return this;
    }

    /**
     * 设置保存路径(如TF卡路径:/storage/E2FA-0D00/youdo/--->/storage/E2FA-0D00/youdo/Video/2025-06-27/)
     */
    public UVCCameraHelper setSaveRootPath(final String path) {
        mSavePath = path;
        if (mCameraClient != null) {
            mCameraClient.performAction(new CameraAction(ACTION_SET_SAVE_PATH, mSavePath));
        }
        return this;
    }

    /**
     * 获取截屏的保存路径(/storage/emulated/0/DCIM/USBCamera)
     */
    public String getPicturePath() {
        /*if (mCameraClient != null) {
            CameraAction act = mCameraClient.getAttribute(ACTION_GET_SAVE_PICTURE_PATH);
            if (act != null) {
                return act.getString();
            }
        }*/
        return mSavePath + "/Video";
    }

    /**
     * 获取录像的保存路径(/storage/emulated/0/Movies/USBCamera)
     */
    public String getRecordPath() {
        /*if (mCameraClient != null) {
            CameraAction act = mCameraClient.getAttribute(ACTION_GET_SAVE_MOVIES_PATH);
            if (act != null) {
                return act.getString();
            }
        }*/
        return mSavePath + "/Picture";
    }

    /**
     * 在 onCreate 中，权限申请通过后执行
     */
    public void initUVCCamera(Context context, final ConnectCallback listener) {
        if (DEBUG) Log.v(TAG, "initUVCCamera");
        this.mContext = context;
        this.listener = listener;
        this.mUSBMonitor = new USBMonitor(context.getApplicationContext(), new USBMonitor.OnDeviceConnectListener() {
            /**
             * 插入USB或检测到USB时执行
             */
            public void onAttach(UsbDevice device) {
                if (DEBUG) Log.v(TAG, "OnDeviceConnectListener#onAttach:onAttachUsbDevice");
                if (listener != null) {
                    listener.onCheckUsbDevice(device);
                }
            }

            public void onDeviceOpen(UsbDevice device, USBMonitor.UsbControlBlock ctrlBlock, boolean createNew) {
                if (DEBUG) Log.v(TAG, "OnDeviceConnectListener#onConnect:");// 不会执行到
            }

            public void onDeviceClose(UsbDevice device, USBMonitor.UsbControlBlock ctrlBlock) {
                if (DEBUG) Log.v(TAG, "OnDeviceConnectListener#onDisconnect:");// 不会执行到
            }

            /**
             * 拔掉USB时执行
             */
            public void onDetach(UsbDevice device) {
                if (DEBUG) Log.v(TAG, "OnDeviceConnectListener#onDetach:");
                closeUVCCamera(device);
            }

            @Override
            public void onCancel(UsbDevice device) {
                if (DEBUG) Log.v(TAG, "OnDeviceConnectListener#onCancel:");
                if (listener != null) {
                    listener.onDeviceAvailable(false);
                }
            }
        });
        final List<DeviceFilter> filters = DeviceFilter.getDeviceFilters(mContext, R.xml.device_filter);
        mUSBMonitor.setDeviceFilter(filters);
    }


    /**
     * 在 onResume 中执行
     * RenderThread started
     * onAttachUsbDevice
     * openUVCCamera
     */
    public void register() {
        if (DEBUG) Log.v(TAG, "start: registerUSB");

        if (this.mUSBMonitor != null) {
            this.mUSBMonitor.register();
        }
    }

    /**
     * 在 onPause 中执行
     * RenderThread finishing
     */
    public void unregister() {
        if (DEBUG) Log.v(TAG, "stop:unregisterUSB and removeSurface");
        previewSurfaceView(false);
        previewTextureView(false);
        if (this.mUSBMonitor != null) {
            this.mUSBMonitor.unregister();
        }
        if (listener != null) {
            listener.onDeviceAvailable(false);
        }
    }

    /**
     * 在 onDestroy 中执行
     */
    public void onDestroy() {
        if (DEBUG) Log.v(TAG, "onDestroy:");
        if (mCameraClient != null) {
            mCameraClient.release();
            mCameraClient = null;
        }
    }

    /**
     * 打开相机
     */
    public void openUVCCamera() {
        if (DEBUG) Log.v(TAG, "打开相机,openUVCCamera:tryOpenUVCCamera");
        openUVCCamera(0);
    }

    /**
     * 打开相机
     */
    private void openUVCCamera(final int index) {
        if (DEBUG) Log.v(TAG, "openUVCCamera:index=" + index);
        if (!mUSBMonitor.isRegistered()) return;
        final List<UsbDevice> list = mUSBMonitor.getDeviceList();
        if (DEBUG) Log.v(TAG, "openUVCCamera:size=" + list.size());
        if (list.size() > index) {
            if (listener != null) {
                listener.onDeviceAvailable(false);
                listener.onPreviewAvailable(false);
            }
            if (mCameraClient == null)
                mCameraClient = new CameraClient(mContext, mCameraListener);
            mCameraClient.select(list.get(index));
            mCameraClient.resize(mCurrentWidth, mCurrentHeight);
            mCameraClient.performAction(new CameraAction(ACTION_SET_DEBUG_MODE, DEBUG));
            mCameraClient.performAction(new CameraAction(ACTION_SET_FRAME_CALLBACK, mEnableFrameCallback));
            mCameraClient.performAction(new CameraAction(ACTION_SET_SAVE_MODE, mSaveMode));
            mCameraClient.performAction(new CameraAction(ACTION_SET_SAVE_PATH, mSavePath));
            mCameraClient.performAction(new CameraAction(ACTION_SET_AUDIO_RECORD, mAudioRecord));
            mCameraClient.connect();
        }
    }

    private final ICameraClientCallback mCameraListener = new ICameraClientCallback() {
        @Override
        public void onConnect(UsbDevice device) {
            if (DEBUG) Log.v(TAG, "onConnect:");
            if (listener != null) {
                listener.onOpenUsbDevice(device);
                listener.onDeviceAvailable(true);
                listener.onPreviewAvailable(true);
            }
            // start UVCService
            final Intent intent = new Intent(mContext, UVCService.class);
            mContext.startService(intent);
        }

        @Override
        public void onDisconnect(UsbDevice device) {
            if (DEBUG) Log.v(TAG, "onDisconnect:");
            if (listener != null) {
                listener.onDeviceAvailable(false);
                listener.onPreviewAvailable(false);
            }
            closeUVCCamera(device);
        }

        @Override
        public void onCameraChange(int status, String msg) {
            if (DEBUG) Log.v(TAG, "onCameraChange:" + status + ",msg: " + msg);
            if (listener != null) {
                listener.onCameraChange(status, msg);
            }
        }

        @Override
        public void onFrameReceived(BufferWrapper data) {
            if (DEBUG) Log.v(TAG, "onFrameReceived:" + data);
            if (listener != null) {
                listener.onFrameReceived(data);
            }
        }
    };

    /**
     * 关闭相机,Stop service
     */
    public synchronized void closeUVCCamera(UsbDevice device) {
        if (mCameraClient != null) {
            Log.e(TAG, "Stop CameraClient:");
            mCameraClient.disconnect();
            mCameraClient.release();
            mCameraClient = null;
        }
        // stop UVCService
        Log.e(TAG, "Stop UVCService:");
        final Intent intent = new Intent(mContext, UVCService.class);
        mContext.stopService(intent);
        // 退出app
        if (listener != null) {
            listener.onCloseUsbDevice(device);
        }
        Log.e(TAG, "Stop App:");
    }

    /**
     * 预览 SurfaceView
     */
    public void previewSurfaceView(boolean isPreview) {
        if (mCameraClient == null || mCameraViewSub == null) {
            if (DEBUG)
                Log.v(TAG, "previewSurfaceView: " + isPreview + ",Client: " + (mCameraClient == null) + ",ViewSub: " + (mCameraViewSub == null));
            return;
        } else if (mCameraViewSub.getHolder() == null) {
            if (DEBUG) Log.v(TAG, "previewSurfaceView: " + isPreview + ",getHolder() is null");
            return;
        } else if (mCameraViewSub.getHolder().getSurface() == null) {
            if (DEBUG)
                Log.v(TAG, "previewSurfaceView: " + isPreview + ",getHolder().getSurface() is null");
            return;
        }
        if (DEBUG) Log.v(TAG, "previewSurfaceView: " + isPreview);
        if (isPreview) {
            mCameraClient.addSurface(mCameraViewSub.getHolder().getSurface(), false);
        } else {
            mCameraClient.removeSurface(mCameraViewSub.getHolder().getSurface());
        }
    }

    /**
     * 预览 TextureView
     * 打开app后,再插入USB时,getSurface() = null,执行removeSurface会闪退;
     */
    public void previewTextureView(boolean isPreview) {
        if (mCameraClient == null || mCameraView == null) {
            if (DEBUG)
                Log.v(TAG, "previewTextureView: " + isPreview + ",mCameraClient: " + (mCameraClient == null) + ",mCameraView: " + (mCameraView == null));
            return;
        } else if (mCameraView.getSurface() == null) {
            if (DEBUG)
                Log.v(TAG, "previewTextureView: " + isPreview + ",getSurface: " + mCameraView.getSurface());
            return;
        }
        if (DEBUG)
            Log.v(TAG, "previewTextureView: " + isPreview + ",hashCode: " + mCameraView.getSurface().hashCode());
        if (isPreview) {
            mCameraClient.addSurface(mCameraView.getSurface(), false);
        } else {
            mCameraClient.removeSurface(mCameraView.getSurface());
        }
    }

    public void addSessionSurface(CameraViewInterface viewInterface, boolean isPreview) {
        if (mCameraClient == null || mCameraView == null) {
            return;
        }
        if (DEBUG) Log.v(TAG, "previewTextureView: " + isPreview);
        if (isPreview) {
            mCameraClient.addSurface(viewInterface.getSurface(), false);
        } else {
            mCameraClient.removeSurface(viewInterface.getSurface());
        }
    }

    /**
     * 录像状态
     */
    public boolean isRecording() {
        if (mCameraClient == null) {
            return false;
        }
        return mCameraClient.isRecording();
    }

    public boolean isConnected() {
        if (mCameraClient == null) {
            return false;
        }
        return null != mCameraClient.getDevice();
    }

    /**
     * 录像
     */
    public void recordVideo(boolean start) {
        Log.e("youdo", "recordVideo start = " + start);
        if (mCameraClient != null) {
            mCameraClient.performAction(new CameraAction(ACTION_SET_SEGMENT_PERIOD, mSegmentPeriod));
            if (start) {
                mCameraClient.startRecording();
            } else {
                mCameraClient.stopRecording();
            }
        }
    }

    /**
     * 拍照
     */
    public void takePicture() {
        if (mCameraClient != null) {
            mCameraClient.captureStill(MediaMuxerWrapper.getDateTimeString() + ".jpg");
        }
    }

    /**
     * 设置镜像
     */
    public UVCCameraHelper setOrientation(int open, int horizontal) {
        if (mCameraClient != null) {
            mCameraClient.setOrientation(open, horizontal);
        }
        return this;
    }

}
